<template>
  <div class="tree-container">
    <!-- 搜索框 -->
    <div class="tree-search" v-if="conf.showSearch">
      <el-input
        v-model="filterText"
        placeholder="输入关键字过滤"
        clearable
        prefix-icon="Search"
        @clear="handleSearchClear"
      />
    </div>

    <!-- 树形组件 -->
    <el-tree
      ref="treeRef"
      :data="filteredData"
      :props="treeProps"
      :show-checkbox="conf['show-checkbox']"
      :default-expand-all="conf['default-expand-all']"
      :check-on-click-node="conf['check-on-click-node']"
      :check-strictly="conf['check-strictly']"
      :draggable="conf.draggable"
      :node-key="conf.props.value || 'value'"
      :lazy="conf.advanced?.lazy"
      :filter-node-method="filterNode"
      v-model:checked-keys="conf.modelValue"
      @check="handleCheck"
      @node-click="handleNodeClick"
    >
      <template #default="{ node, data }">
        <span class="custom-tree-node">
          <span :class="{ 'highlight-text': isMatch(node, data) }">
            {{ node.label }}
          </span>
          <span v-if="conf.showOperation" class="tree-operations">
            <el-button
              v-for="(btn, idx) in conf.operations"
              :key="idx"
              :type="btn.type || 'text'"
              :icon="btn.icon"
              size="small"
              @click.stop="handleOperation(btn, node, data)"
            >
              {{ btn.label }}
            </el-button>
          </span>
        </span>
      </template>
    </el-tree>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType, ref, computed, watch, nextTick } from 'vue'
import { ElTree, ElMessage } from 'element-plus'

interface TreeNode {
  [key: string]: any
  children?: TreeNode[]
}
type ButtonType = 'default' | 'primary' | 'success' | 'warning' | 'info' | 'text' | 'danger'
interface TreeConfig {
  id: string
  modelValue: any[]
  data: TreeNode[]
  dataType: string
  action: string 
  props: {
    label: string
    value: string
    children: string
    disabled?: (data: any, node: any) => boolean
  }
  'show-checkbox': boolean
  'default-expand-all': boolean
  'check-on-click-node': boolean
  'check-strictly': boolean
  draggable: boolean
  showOperation: boolean
  showSearch?: boolean
  operations: Array<{
    label: string
    icon: string
    type?: ButtonType
    handler: (node: any, data: any) => void
  }>
  advanced?: {
    lazy?: boolean
    load?: (node: any, resolve: (data: any[]) => void) => void
  }
}

export default defineComponent({
  name: 'FancyTree',
  props: {
    conf: {
      type: Object as PropType<TreeConfig>,
      required: true
    },
    showSearch: {
      type: Boolean,
      default: true
    }
  },
  emits: ['update:modelValue', 'node-click', 'operation-click'],
  setup(props, { emit }) {
    const treeRef = ref<InstanceType<typeof ElTree>>()
    const filterText = ref('')
    const treeData = ref<TreeNode[]>([])

    // 处理后的数据（包含搜索过滤）
    const filteredData = computed(() => {
      if (!filterText.value) return treeData.value
      return filterTreeData(treeData.value, filterText.value)
    })

    // 树形属性映射
    const treeProps = computed(() => ({
      label: props.conf.props?.label || 'label',
      children: props.conf.props?.children || 'children',
      disabled: props.conf.props?.disabled || (() => false)
    }))

    // 初始化树数据
    const initTreeData = async () => {
      try {
        if (props.conf.dataType === 'static') {
          treeData.value = props.conf.data || []
          return
        }

        const response = await fetch(props.conf.action)
        treeData.value = await response.json()
      } catch (error) {
        ElMessage.error('加载树数据失败')
        console.error('加载树数据失败:', error)
        treeData.value = []
      }
    }

    // 树数据过滤方法
    const filterTreeData = (nodes: TreeNode[], keyword: string): TreeNode[] => {
      if (!keyword) return nodes
      
      return nodes
        .map(node => ({ ...node })) // 浅拷贝节点避免修改原始数据
        .filter(node => {
          const match = filterNode(keyword, node)
          
          // 如果有子节点，递归过滤
          if (node.children && node.children.length) {
            node.children = filterTreeData(node.children, keyword)
            // 保留当前节点如果它匹配或者它的子节点有匹配
            return match || node.children.length > 0
          }
          
          // 没有子节点，只根据自身匹配情况决定
          return match
        })
    }

    // Element Plus 过滤方法（保持原有逻辑不变）
    const filterNode = (value: string, data: TreeNode): boolean => {
      if (!value) return true
      return data[props.conf.props?.label || 'label'].includes(value)
    }

    // 是否匹配搜索条件
    const isMatch = (node: any, data: TreeNode) => {
      return filterText.value && 
        data[props.conf.props.label].includes(filterText.value)
    }

    // 清空搜索
    const handleSearchClear = () => {
      filterText.value = ''
      if (treeRef.value) {
        treeRef.value.filter('')
      }
    }

    const handleOperation = (btn: any, node: any, data: any) => {
      emit('operation-click', { btn, node, data })
      if (typeof btn.handler === 'function') {
        btn.handler(node, data)
      }
    }

    const handleCheck = (data: TreeNode, checked: any) => {
      emit('update:modelValue', checked.checkedKeys)
    }

    const handleNodeClick = (data: TreeNode) => {
      emit('node-click', data)
      if (props.conf['check-on-click-node']) {
        const currentKeys = [...props.conf.modelValue]
        const key = data[props.conf.props.value]
        const index = currentKeys.indexOf(key)
        
        if (index > -1) {
          currentKeys.splice(index, 1)
        } else {
          currentKeys.push(key)
        }
        emit('update:modelValue', currentKeys)
      }
    }

    // 监听数据变化
    watch(() => props.conf.data, initTreeData, { immediate: true })

    // 监听搜索文本变化
    watch(filterText, (val) => {
      nextTick(() => {
        if (treeRef.value) {
          treeRef.value.filter(val)
        }
      })
    })

    return {
      treeRef,
      filterText,
      filteredData,
      treeProps,
      filterNode,
      isMatch,
      handleSearchClear,
      handleOperation,
      handleCheck,
      handleNodeClick
    }
  }
})
</script>

<style scoped>
/* 样式保持不变 */
.tree-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.tree-search {
  margin-bottom: 10px;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.tree-operations {
  margin-left: 10px;
}

.highlight-text {
  color: var(--el-color-primary);
  font-weight: bold;
}
</style>